﻿#ifndef WIDGET_H
#define WIDGET_H

#include <set>
#include <map>
#include <list>

#include <QLabel>
#include <QWidget>
#include <QCheckBox>
#include <QTableView>
#include <QTextCodec>
#include <QStringList>
#include <QMessageBox>

#include <QtNetwork>
#include <QTcpSocket>

#include <QDir>
#include <QFile>
#include <QTime>
#include <QDebug>
#include <QJsonValue>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>

#include <QStandardItem>
#include <QStandardItemModel>

#include "constant.h"
#include "network_tools.h"
#include "contact_person.h"

#include "check_box_widget.h"
#include "operation_widget.h"
#include "search_box_widget.h"
#include "table_head_widget.h"
#include "contact_person_add_dialog.h"
#include "contact_person_modify_dialog.h"


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);

    ~Widget();

signals:
    // 复选框按钮状态发生更改时触发信号
    void checkBoxStateChange();

    // 联系人数量发生变化时触发的信号
    void contactPersonNumberChange();

    // 添加联系人触发的信号
    void addContactPerson(ContactPerson *);

    // 修改联系人触发的信号
    void modifyContactPerson(ContactPerson *);

    // 删除联系人触发的信号
    void deleteContactPerson(list<ContactPerson *> delete_person_list);

private:
    Ui::Widget *ui;

    QWidget *top_layout;                // 顶部件布局
    QWidget *center_layout;             // 中心部件布局

    QPushButton *add_button;            // 添加联系人按钮
    QPushButton *delete_button;         // 删除联系人按钮

    SearchBoxWidget *search_box;        // 搜索框
    CheckBoxWidget *total_check_box;    // 总的复选框
    ContactPersonAddDialog *add_dialog; // 添加联系人对话框

    QTableView *table_view;             // 数据表格

private:
    MysqlTool *mysql;                   // Mysql 的工具类

    bool isStartMysql = false;          // Mysql 是否正常启动了

    QStringList table_head_text;        // 表头的标题内容

    int checkBoxSelectCount = 0;        // 选中 CheckBox 的数量

private:
    list<int> show_person_id_list;                                  // 展示行联系人 ID 列表

    list<int> hidden_person_id_list;                                // 隐藏行联系人 ID 列表

    QJsonArray contact_person_json_array;                           // 通讯录联系人列表对应的 Json 列表

    list<ContactPerson *> contact_person_list;                      // 通讯录联系人列表

private:
    QStandardItemModel *data_model;                                 // 通讯录的全部数据模型

    list<CheckBoxWidget *> check_box_list;                          // 联系人复选框列表    

    map<ContactPerson *, OperationWidget *> operation_dialog_map;   // 联系人操作按钮列表

private:
    bool isStartServer = false;         // Server是否开启了服务

    QString receive_msg;                // 接收服务端的信息

    quint16 server_port;                // 服务器PID

    QHostAddress server_ip;             // 服务器IP

    QTcpSocket tcp_socket;              // 服务器套接字对象

private:
    // 项目UI初始化
    void initUi();

    // 项目UI数据初始化
    void initUiData();

    // 项目数据初始化
    void initData();

    // 项目事件连接初始化
    void initConnect();

private:
    // 测试使用 获取一个联系人
    ContactPerson *getContectPerson();

    // 测试使用 打印全部联系人的信息
    void prinfAllContactPersonInfomation();

private:
    // 添加联系人对应的Ui事件
    void addContactPersonUiEvent(int row, ContactPerson *);

    // TableView 表格填充联系人
    void tableViewFillContactPerson(int row, ContactPerson *);

    // 通过联系人指针获取对应的行
    int getTableRowById(int contact_person_id);

    // 通过联系人 ID 获取对应的联系人
    ContactPerson *getContactPersonById(int contact_person_id);

    // 展示 TableView 的全部行
    void showTableViewAllRow();

    // 获取数据库中的全部数据
    void getDatabaseAllData();

    // 填充 TableView 中新添加联系人的 ID(弃用)
    void fillTableViewAddContactPersonId(ContactPerson *);

private:
    // 启动客户端, 与服务器通信
    void startClient();

    // 结束客户端
    void endClient();

    // 获取用户ID
    int getUserId();

    // 向服务端发送信息
    void sendMessage(QString msg);

private:    
    // 创建 data.json 存放地址的文件夹
    void createTargetDir();

    // 从 data.json 中获取全部联系人的数据
    void readDataFromJson();

    // 将全部联系人的数据写到 data.json 中
    void writeDataToJson();

    // 获取 Json 文件的全部数据
    void getJsonFileAllData();

    // 向 JsonArray 中添加当前联系人的数据
    void addContactPersonToJsonArray(ContactPerson *person);

    // 从 JsonArray 中删除当前联系人的数据
    void deleteContactPersonFromJsonArray(ContactPerson *person);

    // 通过 JsonObject 获取 ContactPerson 实例
    ContactPerson *changeJsonObjectToContectPerson(QJsonObject &object);
};
#endif // WIDGET_H
